﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Core.DataAccess.Model.Project.Order;
using Core.Framework.EntityExtend;
using Core.Framework.Model.Common;
using Core.Framework.Util;
using Core.Framework.Util.Common;
using Core.IBusiness.IEntrepotModule;
using Core.IBusiness.IOrderModule;
using Core.IBusiness.IOrderModule.Model;
using Core.IBusiness.IPushModule;
using Microsoft.AspNetCore.Http;
using SDK.ApiService;
using SDK.ApiService.TrackNode;
using SDK.ApiService.TrackNode.Model;

namespace Core.Business.OrderModule
{
    public class Order : BaseHttpPipelineInfo, IOrder
    {
        IShopPush iShopPush;
        IEntrepot iEntrepot;

        public Order(IShopPush iShopPush, IEntrepot iEntrepot, IHttpContextAccessor iHttp) : base(iHttp) {
            this.iShopPush = iShopPush;
            this.iEntrepot = iEntrepot;
        }

        public MethodResult<int> AddUserCart(OrderUserCart model)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    var cart = context
                    .OrderUserCart
                    .Where(a => a.ProductKey == model.ProductKey && a.ProjectToken == model.ProjectToken && a.UserKey == model.UserKey)
                    .FirstOrDefault();

                    if (cart?.Id > 0)
                    {
                        model.Id = cart.Id;

                        context
                            .OrderUserCart
                            .BulkUpdate(new OrderUserCart
                            {
                                ProductCount = model.ProductCount + cart.ProductCount,
                                Price = model.Price,
                                DisCountPrice = model.DisCountPrice,
                                Content = model.Content,
                                UpdateLastTime = DateTime.Now
                            })
                            .Where(a => a.Id == model.Id);
                    }
                    else
                    {
                        context.OrderUserCart.Add(model);
                    }

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = model.Id, Discription = error };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Date = 0, Discription = e.Message };
            }
        }

        public MethodResult<int> CancelOrder(int order_key, string project_token)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {

                    context
                            .OrderBasis
                            .BulkUpdate(new OrderBasis
                            {
                                OrderStatus = (int)OrderStatus.order_delete
                            })
                            .Where(a => a.OrderKey == order_key && a.ProjectToken == project_token);


                    int row = context.BeginSaveChanges(out string error);


                    #region Use iShopPush

                    var order = context
                        .OrderBasis
                        .Select(a => new {
                            userKey = a.UserKey,
                            OrderKey = a.OrderKey
                        })
                        .Where(a => a.OrderKey == order_key)
                        .First();
                    

                    this.iShopPush.OrderCancel(new IBusiness.IPushModule.Model.OrderCancelModel {
                        Title = $"您的订单 TT19940503 已取消",
                        ClientToken = iClientInfo.Token,
                        MessageKey = order.userKey.ToString(),
                        MessageContent = new IBusiness.IPushModule.Model.OrderCancelContent {
                            Order = new IBusiness.IPushModule.Model.OrderModel {
                                Id = order_key
                            },
                            Products = this.GetPushModuleProductsInfoByOrderKey(context,order_key),
                            // TODO 这里应该新增 订单取消备注信息，目前的没有
                            Remark = "您的订单取消已提交"
                        }
                    });
                    #endregion


                    return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Date = 0, Discription = e.Message };
            }

        }

        public MethodResult<int> DeleteOrder(int order_key, string project_token)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {

                    context
                            .OrderBasis
                            .Delete(a => a.OrderKey == order_key && a.ProjectToken == project_token);

                    context
                            .OrderAddress
                            .Delete(a => a.OrderKey == order_key);

                    context
                            .OrderLog
                            .Delete(a => a.OrderKey == order_key);

                    context
                            .OrderPay
                            .Delete(a => a.OrderKey == order_key);

                    context
                            .OrderProduct
                            .Delete(a => a.OrderKey == order_key);

                    context
                            .OrderRefund
                            .Delete(a => a.OrderKey == order_key);

                    context
                            .OrderServe
                            .Delete(a => a.OrderKey == order_key);

                    context
                            .OrderShipments
                            .Delete(a => a.OrderKey == order_key);

                    context
                            .OrderReturns
                            .Delete(a => a.OrderKey == order_key);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Date = 0, Discription = e.Message };
            }
        }

        public MethodResult<int> DeleteUserCart(int cart_key, string project_token)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                            .OrderUserCart
                            .Delete(a => a.Id == cart_key && a.ProjectToken == project_token);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Date = 0, Discription = e.Message };
            }
        }

        public MethodResult<List<OrderBasis>> GetOrder(string project_token, OrderStatus order_statu, OrderType order_type, Pagination pagination)
        {
            
            Expression<Func<OrderBasis, bool>> lamdba = (a) => a.ProjectToken == project_token;

            switch (order_statu)
            {
                case OrderStatus.order_init:
                    lamdba = lamdba.And(a => a.OrderType == (int)order_type && a.OrderStatus != 4);
                    break;
                default:
                    lamdba = lamdba.And(a => a.OrderType == (int)order_type && a.OrderStatus == (int)order_statu);
                    break;
            }

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    var sources = context
                        .OrderBasis
                        .Where(lamdba)
                        .Pagination(pagination);

                    foreach (var item in sources)
                    {
                        item.OrderProduct = context.OrderProduct.Where(a => a.OrderKey == item.OrderKey).ToList();
                        switch (order_statu)
                        {

                            case OrderStatus.order_shipments:
                            case OrderStatus.order_shipments_check:
                                item.OrderShipments = context.OrderShipments.Where(a => a.OrderKey == item.OrderKey).ToList();
                                item.OrderAddress = context.OrderAddress.Where(a => a.OrderKey == item.OrderKey).ToList();
                                break;

                            case OrderStatus.order_pay:
                                item.OrderPay = context.OrderPay.Where(a => a.OrderKey == item.OrderKey).ToList();
                                break;

                            case OrderStatus.order_returns:
                                item.OrderReturns = context.OrderReturns.Where(a => a.OrderKey == item.OrderKey).ToList();
                                break;

                            case OrderStatus.order_refund:
                                item.OrderRefund = context.OrderRefund.Where(a => a.OrderKey == item.OrderKey).ToList();
                                break;

                            case OrderStatus.order_returns_refund:
                                item.OrderReturns = context.OrderReturns.Where(a => a.OrderKey == item.OrderKey).ToList();
                                item.OrderRefund = context.OrderRefund.Where(a => a.OrderKey == item.OrderKey).ToList();
                                break;
                        }

                    }

                    return new MethodResult<List<OrderBasis>> { IsFinished = true, Date = sources};

                }
            }
            catch (Exception e)
            {
                return new MethodResult<List<OrderBasis>> { IsFinished = false, Discription = e.Message };
            }


        }

        public MethodResult<Dictionary<string, int>> GetOrderCount(int user_key, string project_token)
        {
            try
            {
                List<int> orders;

                using (var context = new ProjectOrderContext())
                {
                    orders = context
                        .OrderBasis
                        .Where(a => a.UserKey == user_key && a.ProjectToken == project_token)
                        .Select(a => a.OrderStatus)
                        .ToList();
                }

                Dictionary<string, int> dictionary = new Dictionary<string, int>();
                dictionary.Add("订单初始化", orders.Where(a => a == (int)OrderStatus.order_init || a == 0).Count());
                dictionary.Add("已审核", orders.Where(a => a == (int)OrderStatus.order_check).Count());
                dictionary.Add("已取消", orders.Where(a => a == (int)OrderStatus.order_delete).Count());
                dictionary.Add("已完成", orders.Where(a => a == (int)OrderStatus.order_ok).Count());
                dictionary.Add("已支付", orders.Where(a => a == (int)OrderStatus.order_pay).Count());
                dictionary.Add("退款", orders.Where(a => a == (int)OrderStatus.order_refund).Count());
                dictionary.Add("退货", orders.Where(a => a == (int)OrderStatus.order_returns).Count());
                dictionary.Add("退货退款", orders.Where(a => a == (int)OrderStatus.order_returns_refund).Count());
                dictionary.Add("订单发货", orders.Where(a => a == (int)OrderStatus.order_shipments).Count());
                dictionary.Add("发货确认", orders.Where(a => a == (int)OrderStatus.order_shipments_check).Count());

                return new MethodResult<Dictionary<string, int>> { IsFinished = true, Date = dictionary };
            }
            catch (Exception e)
            {
                return new MethodResult<Dictionary<string, int>> { IsFinished = false, Discription = e.Message };
            }
        }


        public MethodResult<object> GetOrderItem(int order_key, string project_token, bool isTrackNodeService) 
        {
            var orderResult = this.GetOrderItem(order_key, project_token);

            if (orderResult.IsFinished)
            {

                var shipment = orderResult.Date.OrderShipments?.FirstOrDefault();

                if (shipment != null)
                {
                    if (shipment.ShipmentsType == 0)
                    {
                        if (shipment.CompleteTime == null)
                        {
                            var service = new TrackNodeService(new TrackNodeParameter
                            {
                                Authorization = "e8c93ba0f40842a0a663338180aa97be",
                                No = shipment.ExpressCode,
                                TypeName = shipment.ExpressName
                            });

                            return new MethodResult<object> { 
                                IsFinished = true,
                                Date = new { 
                                    order = orderResult.Date,
                                    track = service.Select()
                                }
                            };
                        }
                        else
                        {
                            // 已完成
                            return new MethodResult<object>
                            {
                                IsFinished = true,
                                Date = new
                                {
                                    order = orderResult.Date,
                                    track = new TrackNodeResult 
                                    {
                                        status = 0,
                                        result = new TrackNodeDataModel { 
                                            deliverystatus = "3",
                                            list = new List<TrajectoryModel> { 
                                                new TrajectoryModel{ 
                                                    status = "订单已完成，感谢您的支持。希望您购物愉快！",
                                                    time = shipment.CompleteTime.ToString(),
                                                }
                                            }
                                        }
                                    }
                                }
                            };
                        }

                    }
                    else
                    {
                        // 未发货
                        return new MethodResult<object>
                        {
                            IsFinished = true,
                            Date = new
                            {
                                order = orderResult.Date,
                                track = new TrackNodeResult
                                {
                                    status = 0,
                                    result = new TrackNodeDataModel
                                    {
                                        deliverystatus = "10",
                                        list = new List<TrajectoryModel> { 
                                            new TrajectoryModel{ 
                                                status = "当前配送方式不支持此查询",
                                                time = DateTime.Now.ToString()
                                            }
                                        }
                                    }
                                }
                            }
                        };
                    }

                }
                else
                {
                    // 未发货
                    return new MethodResult<object>
                    {
                        IsFinished = true,
                        Date = new
                        {
                            order = orderResult.Date,
                            track = new TrackNodeResult
                            {
                                status = 0,
                                result = new TrackNodeDataModel
                                {
                                    deliverystatus = "3",
                                    list = new List<TrajectoryModel>()
                                }
                            }
                        }
                    };
                }

                


            }
            else {
                return new MethodResult<object> { 
                    IsFinished = false, 
                    Discription = orderResult.Discription };
            }

        }


        public MethodResult<OrderBasis> GetOrderItem(int order_key, string project_token)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    var order = context
                        .OrderBasis
                        .Where(a => a.OrderKey == order_key && a.ProjectToken == project_token)
                        .FirstOrDefault();

                    if (order?.OrderKey > 0)
                    {
                        order.OrderProduct = context.OrderProduct.Where(a => a.OrderKey == order.OrderKey).ToList();
                        order.OrderAddress = context.OrderAddress.Where(a => a.OrderKey == order.OrderKey).ToList();

                        switch ((OrderStatus)order.OrderStatus)
                        {
                            case OrderStatus.order_pay:
                            case OrderStatus.order_shipments:
                            case OrderStatus.order_shipments_check:
                                order.OrderPay = context.OrderPay.Where(a => a.OrderKey == order.OrderKey).ToList();
                                order.OrderShipments = context.OrderShipments.Where(a => a.OrderKey == order.OrderKey).ToList();
                                break;

                            case OrderStatus.order_ok:
                                order.OrderPay = context.OrderPay.Where(a => a.OrderKey == order.OrderKey).ToList();
                                order.OrderShipments = context.OrderShipments.Where(a => a.OrderKey == order.OrderKey).ToList();
                                order.OrderServe = context.OrderServe.Where(a => a.OrderKey == order.OrderKey).ToList();
                                order.OrderAccident = context.OrderAccident.Where(a => a.OrderKey == order.OrderKey).ToList();
                                break;

                            case OrderStatus.order_returns:
                            case OrderStatus.order_refund:
                            case OrderStatus.order_returns_refund:
                                order.OrderPay = context.OrderPay.Where(a => a.OrderKey == order.OrderKey).ToList();
                                order.OrderShipments = context.OrderShipments.Where(a => a.OrderKey == order.OrderKey).ToList();
                                order.OrderRefund = context.OrderRefund.Where(a => a.OrderKey == order.OrderKey).ToList();
                                order.OrderReturns = context.OrderReturns.Where(a => a.OrderKey == order.OrderKey).ToList();
                                break;
                        }
                    }

                    return new MethodResult<OrderBasis> { IsFinished = true, Date = order };
                }

            }
            catch (Exception e)
            {
                return new MethodResult<OrderBasis> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<List<OrderBasis>> GetOrderUser(int user_key, string project_token, OrderStatus order_statu, OrderType order_type, Pagination pagination)
        {
            Expression<Func<OrderBasis, bool>> lamdba = (a) => a.UserKey == user_key && a.ProjectToken == project_token;

            switch (order_statu)
            {
                case OrderStatus.order_init:
                    lamdba = lamdba.And(a => a.OrderType == (int)order_type && a.OrderStatus != 4);
                    break;
                default:
                    lamdba = lamdba.And(a => a.OrderType == (int)order_type && a.OrderStatus == (int)order_statu);
                    break;
            }

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    var sources = context
                        .OrderBasis
                        .Where(lamdba)
                        .Pagination(pagination);

                    foreach (var item in sources)
                    {
                        item.OrderProduct = context.OrderProduct.Where(a => a.OrderKey == item.OrderKey).ToList();
                        switch (order_statu)
                        {

                            case OrderStatus.order_shipments:
                            case OrderStatus.order_shipments_check:
                                item.OrderShipments = context.OrderShipments.Where(a => a.OrderKey == item.OrderKey).ToList();
                                item.OrderAddress = context.OrderAddress.Where(a => a.OrderKey == item.OrderKey).ToList();
                                break;

                            case OrderStatus.order_pay:
                                item.OrderPay = context.OrderPay.Where(a => a.OrderKey == item.OrderKey).ToList();
                                break;

                            case OrderStatus.order_returns:
                                item.OrderReturns = context.OrderReturns.Where(a => a.OrderKey == item.OrderKey).ToList();
                                break;

                            case OrderStatus.order_refund:
                                item.OrderRefund = context.OrderRefund.Where(a => a.OrderKey == item.OrderKey).ToList();
                                break;

                            case OrderStatus.order_returns_refund:
                                item.OrderReturns = context.OrderReturns.Where(a => a.OrderKey == item.OrderKey).ToList();
                                item.OrderRefund = context.OrderRefund.Where(a => a.OrderKey == item.OrderKey).ToList();
                                break;
                        }

                    }

                    return new MethodResult<List<OrderBasis>> { IsFinished = true, Date = sources };
                }

            }
            catch (Exception e)
            {
                return new MethodResult<List<OrderBasis>> { IsFinished = false, Discription = e.Message };
            }

        }

        

        public MethodResult<List<OrderUserCart>> GetUserCart(int user_key, string project_token, Pagination pagination)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    var sources = context
                        .OrderUserCart
                        .Where(a => a.UserKey == user_key && a.ProjectToken == project_token)
                        .Pagination(pagination);

                    return new MethodResult<List<OrderUserCart>> { IsFinished = true, Date = sources };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<List<OrderUserCart>> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderAccident(OrderAccident model)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                       .OrderAccident
                       .Add(model);

                    int row = context.SaveChanges();

                    return new MethodResult<int> { IsFinished = true, Date = row };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderAddressUpdate(int order_key, string content)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                       .OrderAddress
                       .BulkUpdate(new OrderAddress
                       {
                           Content = content,
                           UpdateLastTime = DateTime.Now
                       })
                       .Where(a => a.OrderKey == order_key);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderAddressUpdate(int order_key, string content, int product_key)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                       .OrderAddress
                       .Add(new OrderAddress
                       {
                           OrderKey = order_key,
                           Content = content,
                           ProductKey = product_key,
                           RegTime = DateTime.Now
                       });

                    int row = context.SaveChanges();

                    return new MethodResult<int> { IsFinished = true, Date = row };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderLog(OrderLog model, OrderLogType type)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    model.Type = (int)type;
                    context
                       .OrderLog
                       .Add(model);

                    int row = context.SaveChanges();

                    return new MethodResult<int> { IsFinished = true, Date = row };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderPayment(OrderPay payment_ordel)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                       .OrderBasis
                       .BulkUpdate($"order_status = {(int)OrderStatus.order_pay}", $"payment += {payment_ordel.Payment}")
                       .Where(a => a.OrderKey == payment_ordel.OrderKey);

                    context
                       .OrderPay
                       .Add(payment_ordel);

                    int row = context.BeginSaveChanges(out string error);

                    #region Use IShopPushModule
                    this.iShopPush.OrderAlreadyPay(new IBusiness.IPushModule.Model.OrderAlreadyPayModel {
                        Title = $"您的订单 {payment_ordel.OrderKey} 已付款成功",
                        ClientToken = iClientInfo.Token,
                        MessageKey = payment_ordel.UserKey.ToString(),
                        MessageContent = new IBusiness.IPushModule.Model.OrderAlreadyPayContent {
                            Order = new IBusiness.IPushModule.Model.OrderModel {
                                Id = payment_ordel.OrderKey
                            },
                            OrderPay = new IBusiness.IPushModule.Model.OrderPayModel {
                                Payment = payment_ordel.Payment,
                                Info = payment_ordel.Content
                            },
                            Products = this.GetPushModuleProductsInfoByOrderKey(context, payment_ordel.OrderKey)
                        }
                    });
                    #endregion

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderPaymentUpdate(int order_key, decimal price, string project_token)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                       .OrderBasis
                       .BulkUpdate(new OrderBasis
                       {
                           DiscountPrice = price
                       })
                       .Where(a => a.OrderKey == order_key  && a.ProjectToken == project_token);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderRefundApply(OrderRefund refund)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                       .OrderRefund
                       .Add(refund);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderRefundPay(int order_key, decimal payment, DateTime complete)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                       .OrderBasis
                       .BulkUpdate($"order_status = {(int)OrderStatus.order_refund}")
                       .Where(a => a.OrderKey == order_key);

                    context
                       .OrderRefund
                       .BulkUpdate(new OrderRefund
                       {
                           Payment = payment,
                           CompleteTime = complete,
                           EndTime = DateTime.Now,
                           UpdateLastTime = DateTime.Now
                       })
                       .Where(a => a.OrderKey == order_key);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderRefundStuas(int order_key, OrderBitStatu status, DateTime update_last_time)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    if (status == OrderBitStatu.succeed)
                        context
                           .OrderBasis
                           .BulkUpdate($"order_status = {(int)OrderStatus.order_refund}")
                           .Where(a => a.OrderKey == order_key);

                    context
                       .OrderRefund
                       .BulkUpdate(new OrderRefund
                       {
                           Statu = (int)status == 1,
                           UpdateLastTime = update_last_time
                       })
                       .Where(a => a.OrderKey == order_key);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderRefundUpdate(int order_key, int order_refund_key, decimal price)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    var model = new OrderRefund
                    {
                        OrderKey = order_key,
                        OrderRefundKey = order_refund_key,
                        Price = price,
                        Content = "退款订单修改订单金额",
                        RegTime = DateTime.Now
                    };
                    context
                   .OrderRefund
                   .Add(model);

                    int row = context.SaveChanges();

                    return new MethodResult<int> { IsFinished = true, Date = model.Id };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderReturns(List<OrderShipments> shipmentses)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                       .OrderShipments
                       .BulkInsert(shipmentses);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int>  OrderReturnsApply(List<OrderReturns> returnses)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                   .OrderReturns
                   .BulkInsert(returnses);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderServeApply(OrderServe model)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                        .OrderServe
                        .Add(model);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = model.Id };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderServeUpdate(int OrderServe, string content)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                   .OrderServe
                   .BulkUpdate(new OrderServe
                   {
                       Content = content,
                       UpdateLastTime = DateTime.Now
                   })
                   .Where(a => a.Id == OrderServe);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderComment(int orderProductKey)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {

                    context
                        .OrderProduct
                        .BulkUpdate(new OrderProduct
                        {
                            IsComment = true
                        })
                        .Where(a => a.Id == orderProductKey);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }


        public MethodResult<int> OrderShipments(List<OrderShipments> shipmentses)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    var shipmentse = shipmentses.First();
                    int orderKey = shipmentse.OrderKey;

                    var order = context
                        .OrderBasis
                        .Select(a => new {
                            userKey = a.UserKey,
                            OrderKey = a.OrderKey
                        })
                        .Where(a => a.OrderKey == orderKey)
                        .First();

                    context
                       .OrderBasis
                       .BulkUpdate($"order_status = {(int)OrderStatus.order_shipments}")
                       .Where(a => a.OrderKey == orderKey);

                    foreach (var item in shipmentses)
                    {
                        if (item.ProductKey > 0)
                        {
                            context
                               .OrderProduct
                               .BulkUpdate(new OrderProduct
                               {
                                   DeliverGoodsType = item.ShipmentsType,
                                   DeliverGoods = true,
                                   DeliverGoodsCount = item.ProductCount
                               })
                               .Where(a => a.OrderKey == item.OrderKey && a.ProductKey == item.ProductKey);
                        }
                        else
                        {
                            context
                               .OrderProduct
                               .BulkUpdate(new OrderProduct
                               {
                                   DeliverGoods = true
                               })
                               .Where(a => a.OrderKey == item.OrderKey);
                        }
                    }

                    context.OrderShipments.BulkInsert(shipmentses);

                    int row = context.BeginSaveChanges(out string error);

                    #region Use iShopPush

                    this.iShopPush.OrderShipment(new IBusiness.IPushModule.Model.OrderShipmentModel {
                        Title = $"您的订单 {orderKey} 已发货",
                        ClientToken = "system",
                        MessageKey = order.userKey.ToString(),
                        MessageContent = new IBusiness.IPushModule.Model.OrderShipmentContent {
                            Order = new IBusiness.IPushModule.Model.OrderModel {
                                Id = orderKey
                            },
                            Shipment = new IBusiness.IPushModule.Model.ShipmentModel {
                                Type = shipmentse.ExpressType,
                                Name = shipmentse.ExpressName,
                                Code = shipmentse.ExpressCode,
                                Remark = shipmentse.Content
                            },
                            Products = this.GetPushModuleProductsInfoByOrderKey(context, orderKey)
                        }
                    });
                    #endregion

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> OrderShipmentsConfirm(int order_key, int user_key, DateTime complete_time)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                      .OrderBasis
                      .BulkUpdate($"order_status = {(int)OrderStatus.order_shipments_check}")
                      .Where(a => a.OrderKey == order_key);

                    context
                           .OrderShipments
                           .BulkUpdate(new OrderShipments
                           {
                               UserKey = user_key,
                               CompleteTime = complete_time,
                           })
                           .Where(a => a.OrderKey == order_key);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> PlaceTheOrder(OrderBasis orderBasis, List<OrderProduct> products, OrderAddress address)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {

                    context
                      .OrderBasis
                      .Add(orderBasis);

                    context.SaveChanges();

                    if (orderBasis.OrderKey > 0)
                    {

                        var sell = new List<DataAccess.Model.Project.Entrepot.ProductSell>();

                        foreach (var item in products)
                        {
                            item.OrderKey = orderBasis.OrderKey;

                            var jObject = item.ProductInfo.TryToJObject();

                            if (jObject.ContainsKey("skuid"))
                            {
                                // 订单库存处理
                                int skuid = (int)jObject["skuid"];
                                sell.Add(new DataAccess.Model.Project.Entrepot.ProductSell {
                                    OrderKey = orderBasis.OrderKey,
                                    Content = item.Content,
                                    CountStock = item.ProductCount,
                                    SkuKey = skuid,
                                    TemplateKey = item.ProductKey,
                                    RegTime = DateTime.Now,
                                    SupplierKey = item.SupplierKey
                                });
                            }
                        }

                        // 库存处理
                        {
                            var sellResult = this.iEntrepot.ProductSell(sell);
                            if (!sellResult.IsFinished)
                            {
                                context.OrderBasis.Delete(a => a.OrderKey == orderBasis.OrderKey);
                                context.BeginSaveChanges();
                                return new MethodResult<int>
                                {
                                    IsFinished = sellResult.IsFinished,
                                    Date = 0,
                                    Discription = sellResult.Discription
                                };
                            }

                            if (sellResult.Date < products.Count)
                            {
                                context.OrderBasis.Delete(a => a.OrderKey == orderBasis.OrderKey);
                                context.BeginSaveChanges();

                                return new MethodResult<int>
                                {
                                    IsFinished = sellResult.IsFinished,
                                    Date = 0,
                                    Discription = "包含库存不足产品请返回刷新后重试"
                                };
                            }

                        }
                        
                        


                        address.OrderKey = orderBasis.OrderKey;

                        context.OrderProduct.BulkInsert(products);
                        context.OrderAddress.BulkInsert(new List<OrderAddress> { address });

                        // 优惠卷信息
                        if (!string.IsNullOrWhiteSpace(orderBasis.CouponCode))
                        {
                            context.OrderCoupon.BulkUpdate($"IsUse = 1").Where(a => a.Code == orderBasis.CouponCode);
                        }

                        int row = context.BeginSaveChanges(out string error);

                        // 下单失败回滚
                        if (row < 1)
                        {
                            orderBasis.CouponCode = orderBasis.CouponCode.ToLower();
                            context.OrderBasis.Delete(a => a.OrderKey == orderBasis.OrderKey);
                            context.BeginSaveChanges();
                        }

                        return new MethodResult<int> { IsFinished = row > 0, Date = orderBasis.OrderKey, Discription = error };


                    }
                    else
                    {
                        return new MethodResult<int> { IsFinished = false };
                    }

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<int> UpdateUserCartItem(OrderUserCart model)
        {

            try
            {
                using (var context = new ProjectOrderContext())
                {
                    context
                      .OrderUserCart
                      .BulkUpdate(new OrderUserCart
                      {
                          ProductCount = model.ProductCount > 0 ? model.ProductCount : 1,
                          Price = model.Price > 0 ? model.Price : 0,
                          DisCountPrice = model.DisCountPrice > 0 ? model.DisCountPrice : 0
                      })
                      .Where(a => a.Id == model.Id && a.ProjectToken == model.ProjectToken);

                    int row = context.BeginSaveChanges(out string error);

                    return new MethodResult<int> { IsFinished = true, Date = row, Discription = error };

                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }

        

        public MethodResult<int> UserCartOrder(OrderBasis orderBasis, OrderAddress address, List<OrderUserCart> userCarts)
        {


            try
            {
                using (var context = new ProjectOrderContext())
                {


                    context
                  .OrderBasis
                  .Add(orderBasis);

                    context.SaveChanges();

                    if (orderBasis.OrderKey > 0)
                    {
                        address.OrderKey = orderBasis.OrderKey;
                        context.OrderAddress.BulkInsert(new List<OrderAddress> { address });

                        List<OrderProduct> products = new List<OrderProduct>();

                        foreach (var item in userCarts)
                        {
                            context
                                .OrderUserCart
                                .Delete(a => a.Id == item.Id && a.ProjectToken == item.ProjectToken);

                            products.Add(new OrderProduct
                            {
                                OrderKey = orderBasis.OrderKey,
                                ProductKey = item.ProductKey,
                                SupplierKey = item.SupplierKey,
                                ProductCount = item.ProductCount,
                                Price = (decimal)item.Price,
                                DiscountPrice = (decimal)item.DisCountPrice,
                                ProductInfo = item.Content
                            });
                        }

                        context.OrderProduct.BulkInsert(products);

                        if (!string.IsNullOrWhiteSpace(orderBasis.CouponCode))
                        {
                            context.OrderCoupon.BulkUpdate($"IsUse = 1").Where(a => a.Code == orderBasis.CouponCode);
                        }

                        int row = context.BeginSaveChanges(out string error);

                        if (row < 1)
                        {
                            context.OrderBasis.Delete(a => a.OrderKey == orderBasis.OrderKey);
                            context.BeginSaveChanges();
                        }
                        return new MethodResult<int> { IsFinished = row > 0, Date = orderBasis.OrderKey, Discription = error };


                    }
                    else
                    {
                        return new MethodResult<int> { IsFinished = false };
                    }


                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Discription = e.Message };
            }
        }






        public MethodResult<List<OrderUserAddress>> GetUserAddress(OrderUserAddress model)
        {
            try
            {
                using (var context = new ProjectOrderContext())
                {

                    var source = context
                        .OrderUserAddress
                        .Where(a => a.UserKey == model.UserKey && a.ProjectToken == model.ProjectToken)
                        .ToList();

                    return new MethodResult<List<OrderUserAddress>>
                    {
                        IsFinished = true,
                        Date = source
                    };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<List<OrderUserAddress>> { IsFinished = false, Discription = e.Message };
            }
        }


        public MethodResult<int> UserAddressExec(OrderUserAddress model, SqlExecType sqlExecType)
        {
            try
            {
                int row = 0;

                string error = string.Empty;

                using (var context = new ProjectOrderContext())
                {
                    switch (sqlExecType)
                    {
                        case SqlExecType.insert:
                            context
                                .OrderUserAddress
                                .Add(model);
                            break;

                        case SqlExecType.update:
                            int Id = model.Id;
                            string project_token = model.ProjectToken;

                            model.ProjectToken = null;

                            // 默认地址
                            if (model.Default)
                            {
                                context
                                .OrderUserAddress
                                .BulkUpdate(new OrderUserAddress { Default = false })
                                .Where(a => a.Default == true && a.UserKey == model.UserKey && a.ProjectToken == project_token);
                            }

                            context
                                .OrderUserAddress
                                .BulkUpdate(model)
                                .Where(a => a.Id == Id && a.ProjectToken == project_token);

                            break;

                        case SqlExecType.delete:
                            context
                                .OrderUserAddress
                                .Delete(a => a.Id == model.Id && a.ProjectToken == model.ProjectToken);
                            break;
                    }

                    row = context.BeginSaveChanges(out error);
                }

                return new MethodResult<int> { IsFinished = string.IsNullOrWhiteSpace(error), Date = row, Discription = error };

            }
            catch (Exception e)
            {

                return new MethodResult<int> { IsFinished = false, Date = 0, Discription = e.Message };
            }
        }



        /// <summary>
        /// 构造推送的产品信息
        /// </summary>
        private List<IBusiness.IPushModule.Model.ProductModel> GetPushModuleProductsInfoByOrderKey(ProjectOrderContext context, int orderKey)
        {
            var products = context
                   .OrderProduct
                   .Select(a => new
                   {
                       a.OrderKey,
                       a.ProductInfo
                   })
                   .Where(a => a.OrderKey == orderKey)
                   .ToList();

            var productsMap = new List<IBusiness.IPushModule.Model.ProductModel>();

            foreach (var item in products)
            {

                var jObject = item.ProductInfo.TryToJObject();

                //FIXME 这里推送的产品信息未处理
                productsMap.Add(new IBusiness.IPushModule.Model.ProductModel
                {
                    Img = $"service//{jObject["img"]}", // jObject["img"]
                    Title = ""
                });
            }

            return productsMap;
        }


    }
}
